﻿using System;
using System.Reflection;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using Color = System.Drawing.Color;
using ToolTip=System.Windows.Controls.ToolTip;

namespace ShadeTree.Binding.Drivers
{
    public class WPFControlDriver : IControlDriver
    {
        private readonly System.Windows.Controls.Control _control;
        private ToolTip _toolTip = new ToolTip();

        public WPFControlDriver(Control control)
        {
            _control = control;
            _control.ToolTip = _toolTip;
        }

        public Color BackColor
        {
            get
            {
                System.Windows.Media.SolidColorBrush brush = _control.Background as SolidColorBrush;
                if (brush != null)
                {
                    return Color.FromArgb(brush.Color.A, brush.Color.R, brush.Color.G, brush.Color.B);
                }
                else
                {
                    return Color.White;
                }
            }
            set
            {
                var argb = System.Windows.Media.Color.FromArgb(value.A, value.R, value.G, value.B);
                _control.Background = new System.Windows.Media.SolidColorBrush(argb);
            }
        }

        public bool Visible
        {
            get { return _control.IsVisible; }
            set
            {
                _control.Visibility = value ? Visibility.Visible : Visibility.Collapsed;
            }
        }

        public bool Enabled
        {
            get { return _control.IsEnabled; }
            set { _control.IsEnabled = value; }
        }

        public void Focus()
        {
            _control.Focus();
        }

        public string GetKey()
        {
            if (_control.Parent != null)
            {
                return _control.Parent.GetType().FullName + "/" + _control.GetType().FullName + "/" + _control.Name;
            }
            else
            {
                return _control.GetType().FullName + "/" + _control.Name;
            }
        }

        public void OnLostFocus(Action action)
        {
            _control.LostFocus += delegate { action(); };
        }

        public static void FireEvent(object control, string eventName, params object[] args)
        {
            MethodInfo minfo =
                control.GetType().GetMethod("On" + eventName,
                                            BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
            ParameterInfo[] param = minfo.GetParameters();

            if (param.Length == 0)
            {
                minfo.Invoke(control, null);
                return;
            }

            object[] parameters = new object[param.Length];
            for (int i = 0; i < param.Length; i++)
            {
                parameters[i] = Activator.CreateInstance(param[i].ParameterType);

                RoutedEventArgs argument = parameters[i] as RoutedEventArgs;
                if (argument != null)
                {
                    RoutedEvent[] events = EventManager.GetRoutedEventsForOwner(typeof(UIElement));
                    argument.RoutedEvent = Array.Find(events, e => e.Name == eventName);
                }
            }

            minfo.Invoke(control, parameters);
        }

        public void Click()
        {
            FireEvent(_control, "Click");
        }

        public void FireLostFocus()
        {
            
            FireEvent(_control, "LostFocus");
        }

        public bool IsFocused
        {
            get { return _control.IsFocused; }
        }

        public object Control
        {
            get { return _control; }
        }

        public string Text
        {
            get
            {
                ContentControl contentControl = (ContentControl) _control;
                return contentControl == null ? string.Empty : contentControl.Content.ToString();
            }
        }

        public string ToolTipText
        {
            get { return (string) _toolTip.Content; }
            set { _toolTip.Content = value; }
        }
    }
}